package com.bll.tsdoa.utils;

/**
 * @author bll
 * @version 1.0
 * @date 2025/3/2 22:26
 */

import java.util.List;
import java.util.Random;

public class SaUtils {
    private static final int MAX_ITERATIONS = 10; // 固定循环10次
    private static final double INITIAL_TEMP = 1000.0; // 初始温度
    private static final double COOLING_RATE = 0.95; // 降温系数

    /**
     * 模拟退火算法：通过变异扰动生成新解，返回最优或次优个体
     *
     * @param population 种群集合
     *
     * @return 最优或次优的个体
     */
    public Chromosome simulatedAnnealing(List<Chromosome> population) {
        if (population == null || population.isEmpty()) {
            throw new IllegalArgumentException("种群不能为空");
        }

        Random random = new Random();
        // 初始解：从种群中随机选择一个个体
        Chromosome currentSolution = population.get(random.nextInt(population.size()));
        Chromosome bestSolution = currentSolution.copy(); // 全局最优解

        double currentTemp = INITIAL_TEMP;

        for (int i = 0; i < MAX_ITERATIONS; i++) {
            // 1. 生成新解：对当前解进行变异扰动
            Chromosome neighborSolution = mutate(currentSolution.copy());

            // 2. 计算适应度差值（假设适应度越大越好）
            double currentEnergy = currentSolution.getFitness();
            double neighborEnergy = neighborSolution.getFitness();
            double energyDelta = neighborEnergy - currentEnergy;

            // 3. Metropolis准则决定是否接受新解
            if (acceptNewSolution(energyDelta, currentTemp, random)) {
                currentSolution = neighborSolution;
                // 更新全局最优解
                if (currentSolution.getFitness() > bestSolution.getFitness()) {
                    bestSolution = currentSolution.copy();
                }
            }

            // 4. 降温
            currentTemp *= COOLING_RATE;
        }

        return bestSolution;
    }

    /**
     * 变异扰动：随机选择低位翻转一个二进制位
     */
    private Chromosome mutate(Chromosome chromosome) {
        int[] genes = chromosome.getGenes();
        int length = genes.length;
        Random random = new Random();

        // 选择后1/3低位进行突变
        int lowBitStart = (int) (length * 2 / 3.0);
        int pos = lowBitStart + random.nextInt(length - lowBitStart);
        genes[pos] ^= 1; // 翻转位

        chromosome.setGenes(genes);
        chromosome.calculateFitness(); // 更新适应度
        return chromosome;
    }

    /**
     * Metropolis准则：接受次优解的概率
     */
    private boolean acceptNewSolution(double energyDelta, double temp, Random random) {
        if (energyDelta > 0) {
            return true; // 新解更优，直接接受
        }
        double probability = Math.exp(energyDelta / temp); // energyDelta为负，exp结果为(0,1)
        return random.nextDouble() < probability;
    }

    /**
     * 染色体类（需根据实际需求定义）
     */
    static class Chromosome {
        private int[] genes; // 二进制基因数组
        private double fitness; // 适应度

        public Chromosome(int[] genes) {
            this.genes = genes;
            calculateFitness();
        }

        public Chromosome copy() {
            return new Chromosome(genes.clone());
        }

        public void calculateFitness() {
            // 假设适应度为二进制基因的十进制归一化值
            int sum = 0;
            for (int gene : genes) {
                sum = sum * 2 + gene;
            }
            fitness = sum / (Math.pow(2, genes.length) - 1.0);
        }

        public double getFitness() {
            return fitness;
        }

        public int[] getGenes() {
            return genes;
        }

        public void setGenes(int[] genes) {
            this.genes = genes;
            calculateFitness();
        }
    }
}